(function (win) {
  var repository = [];
  var cache = {
    require: function (...args) {
      let prep = [];
      if (Object.prototype.toString.call(args[0]) === "[object Array]") {
        const first = args[0];
        const exportObj = {};
        prep = collectParams(first, exportObj);
      }

      if (Object.prototype.toString.call(args[1]) === "[object Function]") {
        args[1](...prep);
      }
    },
  };
  var collectParams = function (arr, exports) {
    return arr.map(function (val) {
      if (val === "exports") return exports;
      val = path.join(this.componentsPath, val);
      if (cache[val]) return cache[val];
      let rep = repository.find(function (rep) {
        return rep.name === val;
      });
      if (rep === undefined) {
        if (!fs.existsSync(val)) return undefined;
        aux.window.modulePath = val;
        var defineModule = fs.readFileSync(val).toString();
        var script = new vm.Script(defineModule);
        vm.createContext(aux);
        script.runInContext(aux);

        rep = repository.find(function (rep) {
          return rep.name === val;
        });
      }

      let exportsObj = {};

      const ret = rep.entity(...collectParams(rep.params, exportsObj));
      cache[val] = ret ? ret : exportsObj;

      return cache[val];
    });
  };
  win.define = function (name, params, fun) {
    switch (arguments.length) {
      case 1:
        arguments[0]();
        break;
      case 2:
        arguments[1]();
        break;
      case 3:
        repository.push({
          name: name,
          params: params,
          entity: fun,
        });
        break;
    }
  };
  win.require = cache.require;
})(window);
